using System;
using System.Collections.Generic;
using System.Text;
using ACS.Compiler.Tables.Modes;

namespace ACS.Compiler.Synthes
{
    public class StructFormatter
    {
        private StructMode _mode;

        public StructMode Mode
        {
            get { return _mode; }
        }

        public StructFormatter(StructMode mode)
        {
            _mode = mode;
        }

        public void Format()
        {
            Formatter.Current.Format(
               "using System;\n"
             + "using System.Collections.Generic;\n"
             + "using System.Text;\n"
             + "using ACS.Runtime;\n"
             + "using ACS.Runtime.Types;\n"
             + "using ACS.Runtime.Visitors;\n"
             + "\n"
             + "namespace ACS.Generated"
                );
            Formatter.Current.Incr();
            Formatter.Current.Format("{");
            Formatter.Current.Format(String.Format("public class {0} : StructType", Mode.Name));
            Formatter.Current.Incr();
            Formatter.Current.Format("{");
            ForamatFields();
            FormatVisitor();
            FormatAssign();
            Formatter.Current.Decr();
            Formatter.Current.Format("\n}");
            Formatter.Current.Decr();
            Formatter.Current.Format("\n}");
        }

        private void FormatVisitor()
        {
            Formatter.Current.Format(String.Format("\npublic override int Accept(IVisitor visitor)"));
            Formatter.Current.Incr();
            Formatter.Current.Format("{");

            Formatter.Current.Format("int @res = 0;");
            foreach (Field field in Mode.Fields)
            {
                Formatter.Current.Format(String.Format("@res += {0}.Accept(visitor);", field.FieldName));
            }
            Formatter.Current.Format("return @res;");
            Formatter.Current.Decr();
            Formatter.Current.Format("\n}");
        }

        private void FormatAssign()
        {
            Formatter.Current.Format(String.Format("\npublic void Assign({0} from)",  Mode.Name));
            Formatter.Current.Incr();
            Formatter.Current.Format("{");
            foreach (Field field in Mode.Fields)
            {
                Formatter.Current.Format(String.Format("{0}.Assign(from.{0});", field.FieldName));
            }
            Formatter.Current.Decr();
            Formatter.Current.Format("\n}");
            Formatter.Current.Format(String.Format("\npublic override void Assign(BaseType from)"));
            Formatter.Current.Incr();
            Formatter.Current.Format("{");
            Formatter.Current.Format(String.Format("Assign(({0})from);", Mode.Name));
            Formatter.Current.Decr();
            Formatter.Current.Format("\n}");
        }


        private void ForamatFields()
        {
            foreach (Field field in Mode.Fields)
            {
                string decl = field.FieldMode.ToDeclareFormat();
                string occ = "";
                ArrayMode arrMode = field.FieldMode as ArrayMode;
                if (arrMode != null)
                {
                    occ = arrMode.Occurs.ToString();
                }
                Formatter.Current.Format(String.Format("public {0} {1} = new {2}({3});", decl, field.FieldName, decl, occ));
            }
        }
    }
}
